package com.upeng.commons.sql;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.upeng.commons.beans.BeanUtils;
import com.upeng.commons.lang.ClassUtils;

public class ResultSetUtils {

	/**
	 * <p>Iterator ResultSet, inject all fields to appointing class, then return the instance</p>
	 * @param c
	 * @param rs
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> getObjectListUseReflection(Class<T> c, ResultSet rs) throws Exception{
		if(rs == null){
			return null;
		}
		ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = rsmd.getColumnCount();
		if(columnCount < 1){
			return null;
		}else if(columnCount == 1){
			if(ClassUtils.isSystemClass(c)){
				return getJDKObjectListFromResultSet(c, rs);
			}
		}
		Map<String, Object> keyValues = new HashMap<String, Object>(columnCount);
		List<T> objectList = new ArrayList<T>();
		while(rs.next()){
			for(int i=0; i<columnCount; i++){
				String columnName = rsmd.getColumnName(i + 1);
				if(columnName == null){
					columnName = rsmd.getColumnLabel(i + 1);
				}
				keyValues.put(	ColumnNameUtils.toFieldName(columnName), rs.getObject(i + 1));
			}
			objectList.add((T)BeanUtils.inject(c,keyValues));
		}
		return objectList;
	}
	
	public static <T> List<T> getObjectList(Class<T> c, ResultSet rs, Map<String, String> column2Field) throws Exception{
		if(rs == null){
			return null;
		}
		ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = rsmd.getColumnCount();
		if(columnCount < 1){
			return null;
		}else if(columnCount == 1){
			if(ClassUtils.isSystemClass(c)){
				return getJDKObjectListFromResultSet(c, rs);
			}
		}
		Map<String, Object> keyValues = new HashMap<String, Object>(columnCount);
		List<T> objectList = new ArrayList<T>();
		while(rs.next()){
			for(int i=0; i<columnCount; i++){
				String columnName = rsmd.getColumnName(i + 1);
				if(columnName == null){
					columnName = rsmd.getColumnLabel(i + 1);
				}
				keyValues.put(column2Field.get(columnName), rs.getObject(i + 1));
			}
			objectList.add((T)BeanUtils.inject(c,keyValues));
		}
		return objectList;
	}
	
	//get JDK Class instance from ResultSet
	@SuppressWarnings("unchecked")
	private static <T> List<T> getJDKObjectListFromResultSet(Class<T> c, ResultSet rs) throws Exception{
		List<T> objectList = new ArrayList<T>();
		while(rs.next()){
			objectList.add((T)rs.getObject(1));
		}
		return objectList;
	}
	
	/**
	 * <p>Iterator ResultSet, inject all fields to appointing class, if not result found, return null directory</p>
	 * @param c
	 * @param rs
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getObjectUseReflection(Class<T> c, ResultSet rs) throws Exception{
		if(rs == null){
			return null;
		}
		ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = rsmd.getColumnCount();
		if(columnCount < 1){
			return null;
		}else if(columnCount == 1){
			if(ClassUtils.isSystemClass(c)){
				return (T)getJDKObjectFromResultSet(rs);
			}
		}		
		Map<String, Object> keyValues = new HashMap<String, Object>(columnCount);
		if(rs.next()){
			for(int i=0; i<columnCount; i++){
				String columnName = rsmd.getColumnName(i + 1);
				if(columnName == null){
					columnName = rsmd.getColumnLabel(i + 1);
				}
				keyValues.put(ColumnNameUtils.toFieldName(columnName), rs.getObject(i + 1));
			}
			
		}else{
			return null;
		}
		return (T)BeanUtils.inject(c,keyValues);
	}
	
	public static <T> T getObject(Class<T> c, ResultSet rs, Map<String, String> column2Field) throws Exception{
		if(rs == null){
			return null;
		}
		ResultSetMetaData rsmd = rs.getMetaData();
		int columnCount = rsmd.getColumnCount();
		if(columnCount < 1){
			return null;
		}else if(columnCount == 1){
			if(ClassUtils.isSystemClass(c)){
				return (T)getJDKObjectFromResultSet(rs);
			}
		}		
		Map<String, Object> keyValues = new HashMap<String, Object>(columnCount);
		if(rs.next()){
			for(int i=0; i<columnCount; i++){
				String columnName = rsmd.getColumnName(i + 1);
				if(columnName == null){
					columnName = rsmd.getColumnLabel(i + 1);
				}
				keyValues.put(column2Field.get(columnName), rs.getObject(i + 1));
			}
			
		}else{
			return null;
		}
		return (T)BeanUtils.inject(c,keyValues);
	}
	
	////get JDK Class instance from ResultSet
	private static Object getJDKObjectFromResultSet(ResultSet rs) throws Exception{
		if(rs.next()){
			return rs.getObject(1);
		}
		return null;
	}
}
